package niuke.week4;

import java.util.Arrays;
import java.util.Scanner;

/**
 小易有一个古老的游戏机，上面有着经典的游戏俄罗斯方块。因为它比较古老，所以规则和一般的俄罗斯方块不同。
 荧幕上一共有 n 列，每次都会有一个 1 x 1 的方块随机落下，在同一列中，后落下的方块会叠在先前的方块之上，
 当一整行方块都被占满时，这一行会被消去，并得到1分。

 有一天，小易又开了一局游戏，当玩到第 m 个方块落下时他觉得太无聊就关掉了，小易希望你告诉他这局游戏他获得的分数。
 */
public class ELuoSISegTree {
    SegmentTree <Integer>se;

    private Integer[]data;

    private  class SegmentTree<E> {
        private E []data;
        private E []tree;
        Merge<E> merge;
        public SegmentTree(E []array,Merge<E>merge) {
            data = (E[]) new Object[array.length];
            data = Arrays.copyOf(array, array.length);
            tree = (E[])new Object[4*array.length];
            this.merge = merge;
            if(array.length!=0)
                buildSegmentTree(0,0,data.length-1);
        }
        /**
         * Title: buildSegmentTree</p>
         * Description:
         * @param treeIndex,当前数的根节点在tree数组中对应的索引
         * @param l,当前这个节点表示的区间范围[l,r]
         * @param r,
         */
        private void buildSegmentTree(int treeIndex,int l,int r){
            if(l==r) {//为叶子节点
                tree[treeIndex]=data[l];
                return;
            }
            int leftChild = leftChild(treeIndex);
            int rightChild = rightChild(treeIndex);
            int mid = l+(r-l)/2;//中间节点

            buildSegmentTree(leftChild,l,mid);
            buildSegmentTree(rightChild,mid+1,r);
            //当前数的跟节点为两个孩子节点值得中和
            tree[treeIndex] = merge.merge(tree[leftChild],tree[rightChild]);
        }

        public	E query(int queryL,int queryR) {
            if(queryL<0||queryR>data.length-1)
                throw new IllegalArgumentException("参数错误");
            return query(0,0,data.length-1,queryL,queryR);
        }
        /**
         *
         * Description:   根据当前节点去查询给定范围的值

         * @param treeIndex 当前根节点的索引
         * @param l 当前根节点表达式的范围[l,r]
         * @param r
         * @param queryL 查询的范围[queryL,queryR]
         * @param queryR
         * @return
         */
        private E query(int treeIndex,int l,int r,int queryL,int queryR) {
            //查询区间刚好是当前根节点的区间
            if(l==queryL && r==queryR)
                return tree[treeIndex];

            int mid = l+(r-l)/2;
            int leftChild = leftChild(treeIndex);
            int rightChild = rightChild(treeIndex);
            //查询区间在当前根节点的右子树
            if(queryL>=mid+1)
                return query(rightChild,mid+1,r,queryL,queryR);
                //查询区间在当前根节点的左子树
            else if(queryR<=mid)
                return query(leftChild,l,mid,queryL,queryR);
            else {//查询区间在左右子树都存在，，，
                //在左子树[l,mid]查询[queryL,mid],在右子树[mid+1,r]查询[mid,queryR],再将结果融合
                E leftResult = query(leftChild,l,mid,queryL,mid);
                E rightResult = query(rightChild,mid+1,r,mid+1,queryR);
                return merge.merge(leftResult, rightResult);
            }
        }
        //更新
        public void set(int index,E e) {
            if(index>data.length||index<0)
                throw new IllegalArgumentException("参数错误");
            data[index] = e;
            set(0,0,data.length-1,index,e);
        }
        private void set(int treeIndex,int l,int r,int index,E e) {
            if(l==r) {
                tree[treeIndex] = e;
                return ;
            }

            int mid = l+(r-l)/2;
            int leftChild = leftChild(treeIndex);
            int rightChild = rightChild(treeIndex);
            if(index<=mid)
                set(leftChild,l,mid,index,e);
            else
                set(rightChild,mid+1,r,index,e);
            tree[treeIndex] = merge.merge(tree[leftChild],tree[rightChild]);
        }


        public E get(int index) {
            if(index<0||index>data.length)
                throw new IllegalArgumentException("下标错误");
            return data[index];
        }

        public int  size() {
            return data.length;
        }
        //左孩子
        public int leftChild(int k) {
            return 2*k+1;
        }
        //右孩子
        public int rightChild(int k) {
            return 2*k+2;
        }
        @Override
        public String toString() {
            return "SegmentTree ["+"tree="+Arrays.toString(tree)+"]";
        }

    }

    interface Merge<E> {
        E merge(E left,E right);
    }

    public ELuoSISegTree(int[] nums) {
        data = new Integer[nums.length];
        for(int i=0;i<nums.length;i++)
            data[i] = nums[i];
        se = new SegmentTree<Integer>(data, new Merge<Integer>() {
            @Override
            public Integer merge(Integer e1, Integer e2) {
                return Math.min(e1,e2);
            }
        });
    }

    public void update(int i, int val) {
        se.set(i,val);
    }

    public int minRange(int i, int j) {
        return se.query(i,j);
    }




    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();

        int [] c = new int[n];

        for (int i = 0; i < m; i++) {
            int idx = sc.nextInt();
           c[idx-1] +=  1;
        }

        ELuoSISegTree eLuoSISegTree = new ELuoSISegTree(c);
        System.out.println(eLuoSISegTree.minRange(0,n-1));
    }
}